package com.ruibang.glass.quality.service.impl;

import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.constants.RedisKey;
import com.ruibang.glass.common.domain.file.FileBusiness;
import com.ruibang.glass.quality.constant.Constants;
import com.ruibang.glass.quality.constant.QualityErrorCode;
import com.ruibang.glass.quality.domain.req.GrindRangeReq;
import com.ruibang.glass.quality.domain.resp.GrindData;
import com.ruibang.glass.quality.entity.GrindRange;
import com.ruibang.glass.quality.feign.FileApi;
import com.ruibang.glass.quality.mapper.GrindRangeMapper;
import com.ruibang.glass.quality.service.GrindRangeService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.autoconfigure.redis.RedisSingleService;
import com.teaming.cloud.framework2.common.exception.ServiceException;
import com.teaming.cloud.framework2.common.model.ResultBody;
import com.teaming.cloud.framework2.common.pojo.PageRequest;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 成品离线检测-研磨幅 服务实现类
 * </p>
 *
 * @author songJinKang
 * @since 2024-03-20
 */

@Slf4j
@Service
public class GrindRangeServiceImpl extends ServiceImpl<GrindRangeMapper, GrindRange> implements GrindRangeService {

//    @Autowired
//    private RedisSingleService redisService;

    @Autowired
    private RedisSingleService redisService;

    @Autowired
    private FileApi fileApi;

//    @PostConstruct
//    public void init() {
//        List<GrindRange> grindRangeList = this.list();
//        List<GrindData> grindData = baseMapper.getInitData();
//        Map<String, List<GrindData>> grindDataMap = grindData.stream().collect(Collectors.groupingBy(GrindData::getId));
//
//        for (GrindRange grindRange : grindRangeList) {
//            String id = grindRange.getId();
//            List<GrindData> grindDataList = grindDataMap.get(id);
//            if (CollectionUtils.isNotEmpty(grindDataList)) {
//                grindRange.setGrindData(grindDataList);
//            }
//        }
//        this.updateBatchById(grindRangeList);
//    }

    @Override
    public void delete(String id) {
        lambdaUpdate().eq(GrindRange::getId, id).set(GrindRange::getIsDelete, Constants.ONE_STR).update();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insert(GrindRange grindRange) {
        List<String> fileIds = grindRange.getFileIds();
        this.save(grindRange);
        if (CollectionUtils.isNotEmpty(fileIds)) {
            //更新文件对应业务Id
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(grindRange.getFileIds());
            fileBusiness.setBusinessId(grindRange.getId());
            fileApi.updateBusinessById(fileBusiness);
        }

//        GrindRange grindRange = new GrindRange();
//        grindRange.setGlassId(grindRangeAnalysisData.getGlassId());
//        grindRange.setGlassModel(grindRangeAnalysisData.getGlassModel());
//        grindRange.setMeasureDate(grindRangeAnalysisData.getMeasureDate());
//        grindRange.setCheckTime(grindRangeAnalysisData.getCheckTime());
//        grindRange.setProductLineName(grindRangeAnalysisData.getProductLineName());
//        grindRange.setUserId(grindRangeAnalysisData.getUserId());
//        grindRange.setUserName(grindRangeAnalysisData.getUserName());
//        grindRange.setDecide(grindRangeAnalysisData.getDecide());
//        grindRange.setMaxRange(grindRangeAnalysisData.getMaxRange());
//        grindRange.setMax(grindRangeAnalysisData.getMax());
//        grindRange.setMin(grindRangeAnalysisData.getMin());
//        grindRange.setFileId(grindRangeAnalysisData.getFileId());
//        grindRange.setGrindData(grindRangeAnalysisData.getGrindData());
//        List<GrindData> grindData = grindRangeAnalysisData.getGrindData();
//        if (CollectionUtils.isNotEmpty(grindData)) {
//            for (GrindData grindDatum : grindData) {
//                switch (grindDatum.getFieldType()) {
//                    case "f1": {
//                        grindRange.setF1A(grindDatum.getA());
//                        grindRange.setF1B(grindDatum.getB());
//                        grindRange.setF1C(grindDatum.getC());
//                    }
//                    case "f2": {
//                        grindRange.setF2A(grindDatum.getA());
//                        grindRange.setF2B(grindDatum.getB());
//                        grindRange.setF2C(grindDatum.getC());
//                    }
//                    case "f3": {
//                        grindRange.setF3A(grindDatum.getA());
//                        grindRange.setF3B(grindDatum.getB());
//                        grindRange.setF3C(grindDatum.getC());
//                    }
//                    case "f4": {
//                        grindRange.setF4A(grindDatum.getA());
//                        grindRange.setF4B(grindDatum.getB());
//                        grindRange.setF4C(grindDatum.getC());
//                    }
//                    case "f5": {
//                        grindRange.setF5A(grindDatum.getA());
//                        grindRange.setF5B(grindDatum.getB());
//                        grindRange.setF5C(grindDatum.getC());
//                    }
//                    case "f6": {
//                        grindRange.setF6A(grindDatum.getA());
//                        grindRange.setF6B(grindDatum.getB());
//                        grindRange.setF6C(grindDatum.getC());
//                    }
//                    case "f7": {
//                        grindRange.setF7A(grindDatum.getA());
//                        grindRange.setF7B(grindDatum.getB());
//                        grindRange.setF7C(grindDatum.getC());
//                    }
//                    case "f8": {
//                        grindRange.setF8A(grindDatum.getA());
//                        grindRange.setF8B(grindDatum.getB());
//                        grindRange.setF8C(grindDatum.getC());
//                    }
//                    case "f9": {
//                        grindRange.setF9A(grindDatum.getA());
//                        grindRange.setF9B(grindDatum.getB());
//                        grindRange.setF9C(grindDatum.getC());
//                    }
//                    case "f10": {
//                        grindRange.setF10A(grindDatum.getA());
//                        grindRange.setF10B(grindDatum.getB());
//                        grindRange.setF10C(grindDatum.getC());
//                    }
//                    case "f11": {
//                        grindRange.setF11A(grindDatum.getA());
//                        grindRange.setF11B(grindDatum.getB());
//                        grindRange.setF11C(grindDatum.getC());
//                    }
//                    case "f12": {
//                        grindRange.setF12A(grindDatum.getA());
//                        grindRange.setF12B(grindDatum.getB());
//                        grindRange.setF12C(grindDatum.getC());
//                    }
//                    default: {
//                        log.error("位置字段类型：{}", grindDatum.getFieldType());
//                    }
//                }
//            }
//        }
    }

    @Override
    public IPage<GrindRange> pageQuery(PageRequest<GrindRangeReq> pageRequest) {
        GrindRangeReq grindRangeReq = pageRequest.getParam();
        if (grindRangeReq == null) {
            throw new ServiceException(QualityErrorCode.PARAM_ERROR.getCode(), QualityErrorCode.PARAM_ERROR.getMsg());
        }
        QueryWrapper<GrindRange> qw = new QueryWrapper<>();
        qw.lambda().eq(GrindRange::getIsDelete, Constants.ZERO_STR);
        qw.lambda().eq(StringUtils.isNotBlank(grindRangeReq.getGlassId()), GrindRange::getGlassId, grindRangeReq.getGlassId());
        if (grindRangeReq.getStartDate() != null && grindRangeReq.getEndDate() != null) {
            qw.lambda().ge(GrindRange::getMeasureDate, grindRangeReq.getStartDate());
            qw.lambda().le(GrindRange::getMeasureDate, grindRangeReq.getEndDate());
        }
        qw.lambda().orderByDesc(GrindRange::getCreateTime);
        IPage<GrindRange> page = this.page(new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize()), qw.lambda());
        if (page != null && CollectionUtils.isNotEmpty(page.getRecords())) {
            List<GrindRange> grindRanges = page.getRecords();
            List<String> ids = grindRanges.stream().map(GrindRange::getId).collect(Collectors.toList());
            ResultBody<List<FileBusiness>> resultBody = fileApi.getFileBusinessByIds(ids);
            if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
                List<FileBusiness> fileData = resultBody.getData();
                Map<String, FileBusiness> fileMap = fileData.stream().collect(Collectors.toMap(FileBusiness::getBusinessId, e -> e));
                for (GrindRange grindRange : grindRanges) {
                    FileBusiness fileBusiness = fileMap.get(grindRange.getId());
                    if (fileBusiness != null) {
                        grindRange.setFileIds(fileBusiness.getFileIds());
                    }
                }
            }
        }
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(GrindRange grindRange) {
        this.updateById(grindRange);
        //更新文件信息
        if (CollectionUtils.isNotEmpty(grindRange.getDeleteFileIds())) {
            fileApi.deleteByFileIds(grindRange.getDeleteFileIds());
        }
        //新增文件
        if (CollectionUtils.isNotEmpty(grindRange.getFileIds())) {
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setBusinessId(grindRange.getId());
            fileBusiness.setFileIds(grindRange.getFileIds());
            fileApi.updateBusinessById(fileBusiness);
        }
    }


    @Override
    public GrindRange importExcel(MultipartFile file) {
        if (file != null) {
            //上传文件
            ResultBody<String> resultBody = fileApi.uploadFile(file);
            GrindRange gridRange = new GrindRange();
            if (resultBody != null && StringUtils.isNotBlank(resultBody.getData())) {
                gridRange.setUpLoadFileId(resultBody.getData());
            }
            // 创建一个 XSSFWorkbook 对象
            Workbook workbook = null;
            try {
                workbook = new XSSFWorkbook(file.getInputStream());
            } catch (Exception e) {
                //如果不是excel直接上传文件返回
                return gridRange;
//                log.error("创建工作簿失败：{}", e.getMessage());
//                throw new ServiceException(QualityErrorCode.FILE_IS_NOT_EXCEL.getCode(), QualityErrorCode.FILE_IS_NOT_EXCEL.getMsg());
            }


            // 获取第一个工作表
            Sheet sheet = workbook.getSheetAt(0);
            //读取玻璃ID
            gridRange.setGlassId(getValue(sheet, 2, 9));
            //读取测定日期
            Date date = sheet.getRow(2).getCell(5).getDateCellValue();
            gridRange.setMeasureDate(Constants.DATE_FORMAT.format(date));
            //读取抽检时间
            LocalDateTime dateTime = sheet.getRow(2).getCell(7).getLocalDateTimeCellValue();
            gridRange.setCheckTime(dateTime.getHour() + ":" + dateTime.getMinute() + ":" + dateTime.getSecond());
            //读取产线
            String productLineName = getValue(sheet, 2, 15);
            Map<Object, Object> proMap = redisService.hmget(RedisKey.PRODUCT_LINE_GROUP_TYPE);
            if (StringUtils.isNotBlank(productLineName)) {
                gridRange.setProductLineName(productLineName);
                if (proMap != null && proMap.size() > 0) {
                    Map<String, String> proNameMap = new HashMap<>(16);
                    proMap.forEach((k, v) -> {
                        if (v != null && StringUtils.isNotBlank(v.toString())) {
                            proNameMap.put(v.toString(), k.toString());
                        }
                    });
                    gridRange.setProductLine(proNameMap.get(productLineName));
                }
            }
            //读取型号
            gridRange.setGlassModel(getValue(sheet, 2, 1));
            //读取测量人
            String userName = getValue(sheet, 2, 19);
            if (StringUtils.isNotBlank(userName)) {
                Map<Object, Object> userMap = redisService.hmget(RedisKey.USER_GROUP_TYPE);
                if (!userMap.isEmpty()) {
                    Map<String, String> userNameMap = new HashMap<>();
                    userMap.forEach((k, v) -> {
                        if (v != null && StringUtils.isNotBlank(v.toString())) {
                            userNameMap.put(v.toString(), k.toString());
                        }
                    });
                    gridRange.setUserId(userNameMap.get(userName));
                }
            }
            gridRange.setUserName(userName);
            //读取研磨幅数据
            List<GrindData> grindDataList = new ArrayList<>();
            //1H
            GrindData data1 = getGrindData(sheet, 7, 1, "f1");
            grindDataList.add(data1);
            //1H-1
            GrindData data2 = getGrindData(sheet, 7, 3, "f2");
            grindDataList.add(data2);
            //1H-2
            GrindData data3 = getGrindData(sheet, 7, 5, "f3");
            grindDataList.add(data3);
            //2H
            GrindData data4 = getGrindData(sheet, 7, 7, "f4");
            grindDataList.add(data4);
            //2H-2
            GrindData data5 = getGrindData(sheet, 7, 9, "f5");
            grindDataList.add(data5);
            //2H-3
            GrindData data6 = getGrindData(sheet, 7, 11, "f6");
            grindDataList.add(data6);
            //3H
            GrindData data7 = getGrindData(sheet, 7, 13, "f7");
            grindDataList.add(data7);
            //3H-3
            GrindData data8 = getGrindData(sheet, 7, 15, "f8");
            grindDataList.add(data8);
            //3H-4
            GrindData data9 = getGrindData(sheet, 7, 17, "f9");
            grindDataList.add(data9);
            //4H
            GrindData data10 = getGrindData(sheet, 7, 19, "f10");
            grindDataList.add(data10);
            //4H-1
            GrindData data11 = getGrindData(sheet, 7, 21, "f11");
            grindDataList.add(data11);
            //4H-4
            GrindData data12 = getGrindData(sheet, 7, 23, "f12");
            grindDataList.add(data12);


            List<Integer> abData = new ArrayList<>();
            List<Integer> cData = new ArrayList<>();
            for (GrindData grindData : grindDataList) {
                abData.add(grindData.getA());
                abData.add(grindData.getB());
                cData.add(grindData.getC());
            }

            if (CollectionUtils.isNotEmpty(abData)) {
                //计算最大值
                Integer max = abData.stream().filter(Objects::nonNull).min(Integer::compareTo).orElse(0);
                gridRange.setMax(max);

                //计算最小值
                Integer min = abData.stream().filter(Objects::nonNull).max(Integer::compareTo).orElse(0);
                gridRange.setMin(min);
            }
            if (CollectionUtils.isNotEmpty(cData)) {
                //极差最大值
                Integer max = cData.stream().filter(Objects::nonNull).max(Integer::compareTo).orElse(0);
                gridRange.setMaxRange(max);
            }
            gridRange.setGrindData(grindDataList);
            return gridRange;
        }
        return null;
    }


    private GrindData getGrindData(Sheet sheet, int rowIdx, int cellIdx, String fieldType) {
        GrindData grindData = new GrindData();
        Row row = sheet.getRow(rowIdx);
        //A面数据
        Cell aCell = row.getCell(cellIdx);
        int dataA = (int) aCell.getNumericCellValue();
        grindData.setA(dataA);
        //B面数据
        Cell bCell = row.getCell(cellIdx + 1);
        int dataB = (int) bCell.getNumericCellValue();
        grindData.setB(dataB);
        //取样点
        Row pointRow = sheet.getRow(rowIdx - 2);
        Cell pointCell = pointRow.getCell(cellIdx);
        String pointValue = pointCell.getStringCellValue();
        if (StringUtil.isNotEmpty(pointValue)) {
            grindData.setPoint(pointValue);
        }
        //计算差
        if (grindData.getA() != null && grindData.getB() != null) {
            grindData.setC(Math.abs(grindData.getA() - grindData.getB()));
            //判断品级、与合格
            if ((grindData.getA() >= 100 && grindData.getA() <= 300 && grindData.getB() >= 100 && grindData.getB() <= 300) && grindData.getC() <= 100) {
                grindData.setGrade(Constants.GRADE_A);
                grindData.setDecide(Constants.ZERO_STR);
            } else if (((grindData.getA() > 50 && grindData.getA() < 100 && grindData.getB() > 50 && grindData.getB() < 100) ||
                    (grindData.getA() > 300 && grindData.getA() < 350 && grindData.getB() > 300 && grindData.getB() < 350)) &&
                    grindData.getC() <= 100
            ) {
                grindData.setGrade(Constants.GRADE_B);
                grindData.setDecide(Constants.ZERO_STR);
            } else {
                grindData.setGrade(Constants.GRADE_C);
                grindData.setDecide(Constants.ONE_STR);
            }
        }
        return grindData;
    }


    private String getValue(Sheet sheet, int rowIdx, int cellIdx) {
        Row row = sheet.getRow(rowIdx);
        Cell cell = row.getCell(cellIdx);
        if (cell.getCellType().equals(CellType.NUMERIC)) {
            // 如果是数值类型，则将数值转换为字符串
            return String.valueOf(cell.getNumericCellValue());
        } else if (cell.getCellType().equals(CellType.STRING)) {
            // 如果是字符串类型，则直接获取字符串值
            return cell.getStringCellValue();
        } else {
            return cell.getStringCellValue();
        }
    }
}
